/* Definitions.cpp
 * Author: mtreece
 * Date: 02/13/2010
 * Purpose:
 *  A file which gets passed around to represent data
 *  that has been read from the configuration file.
 *  Contains data about...
 *    -> Lower limits for ticketline numbers
 *    -> Upper limits for ticketline numbers
 *    -> Lower limits for powerball numbers
 *    -> Upper limits for powerball numbers
 *    -> Value of the JackPot PowerBall.
 *    -> Value of a ticket who's matched various
 *       numbers off of a winning TicketLine.
 * 
 *  The above data is known after a ConfReader loads
 *  the information into this Definitions object.
 *  Once that is done...
 *  An instantiated Definitions file do...
 *    -> Generate a random TicketLine number for
 *       usage on a TicketLine object
 *    -> Generate a random TicketLine PB number for
 *       usage on a TicketLine object
 *    -> Given a TicketLine object and a winning 
 *       TicketLine, return a MoneyWorth value
 *       representing the match up, loading the 
 *       MoneyWorth with a flag whether or not
 *       it's worth the JackPot.
 */

#include "Definitions.h"

Definitions::Definitions(){
	/* dummy */
}

Definitions::Definitions(unsigned int lowerNum, unsigned int upperNum,
                         unsigned int lowerPB,  unsigned int upperPB,
                         unsigned int ticketCost, int verbose,
                         unsigned int matchingRewards[][2]){

	/***** Explanation of algorithm-ish ****
	 * "matchingRewards[regNums][binary_PB]" returns worth 
	 *  of a ticket who has regNums-matching regular numbers
	 *  and binary_PB (either 0 or 1) PB matching.
	 */

	/*** Load the limits...  ***/
	this->lowerNum = lowerNum;
	this->upperNum = upperNum;
	this->lowerPB  = lowerPB;
	this->upperPB  = upperPB;

	this->ticketCost = ticketCost;
	this->verbose = verbose;

	/*** Copy over the matchingRewards to storage ***/
	for(int i=0; i<6; i++){
		for(int j=0; j<2; j++){
			this->matchingRewards[i][j] 
			       = matchingRewards[i][j];
		}
	}

	/*** Seed the main generator... ***/
	/* srand( time(NULL) ); */

	/** This uses the microsecond approach... */
	/** src: http://www.guyrutenberg.com/2007/09/03/seeding-srand/ **/
	timeval t1;
	gettimeofday(&t1, NULL);
	srand(t1.tv_usec * t1.tv_sec);
}

int Definitions::getRandNum(int lower, int upper){
	return (int) (((double) rand() / RAND_MAX)*(upper - lower) + lower);
}

int Definitions::getRandNum(){
	return getRandNum(lowerNum, upperNum);
}

int Definitions::getRandPBNum(){
	return getRandNum(lowerPB, upperPB);
}

MoneyWorth* Definitions::getWorth(TicketLine* winner, TicketLine* check){
	int normalMatches = 0, pbMatches = 0;
	for(int i=0; i<5; i++){
		if(hasNum(winner->line, check->line[i]))
			normalMatches++;
	}
	if(winner->pb == check->pb) pbMatches = 1;
	return new MoneyWorth(
	                   matchingRewards[normalMatches][pbMatches], 
	                   normalMatches == 5 && pbMatches
	           );
}

int Definitions::hasNum(int array[], int num){
	/* Refactoring idea...
	 *  This array will be sorted via defined
	 *  usage for use-case; can terminate with a 0
	 *  as soon as it's first encountered number
	 *  is larger than 'num' -- would this
	 *  increase efficiency very much?
	 *  ... or would the additional need to check
	 *  for greater-than decrease any efficiency
	 *  gains?
	 */
	for(int i=0; i<5; i++) if(array[i] == num) return 1;
	return 0;
}

unsigned int Definitions::ticketPrice(){
	return ticketCost;
}

int Definitions::isVerbose(){
	return verbose;
}
